/* 
 COMP20007 Design of Algorithms 

 Read in a text file of text fragments (one per line, first line is fragment length) 
 from stdin and then assemble them using a call to a deBruijn graph assembler.

 Author: Andrew Turpin (aturpin@unimelb.edu.au)
 Date: April 2013

 Usage: ./assemble < filename

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"
#include "vertex.h"
#include "listops.h"
#include "graph.h"
#include "main.h"
#include "hashtable.h"

HASHREC **htable;  // string -> vertex number  mapping

/*
** Print usage message
*/
void
usage(char *exeName) { 
    fprintf(stderr,"Usage: %s < filename\n",exeName);
    fprintf(stderr,"       where\n");
    fprintf(stderr,"          filename - file name of text file with one fragment per line, first line is k==fragment length\n");
}


// If s in h, return number else
// use number_of_vertices as number and insert into h.
// SIDE_EFFECT: may insert s into *h, and may also increment number_of_vertices
//              and may add an element to graph 
Label
get_vertex_label(Graph *g, char *s) {
    HASHREC *p = hashsearch(htable, s);

    Label v;
    if(p == NULL) {
        v = add_vertex(g, s);
        hashinsert(htable, s, v);
    } else {
        v = p->vertex;
    }
    return v;
}

/*
** Read in k
** Then read in each line, taking k-1 prefix 
** and k-1 chars begining at char 1 (hopefully the k-1 suffix)
** Map each to a vertex number, and insert edge in graph.
** SIDE EFFECTS: builds htable and graph
** RETURNS: constructed graph
*/
Graph *
read_input() {
    Graph *graph = create_graph();

    /*
    ** Read in k, the length of fragments
    */
    int k;
    char bufff[32];          // max 31 digits in k: more than enough!
    fgets(bufff, 32, stdin);
    sscanf(bufff, "%d", &k);


    /*
    ** Read in fragments, one per line, until EOF
    ** For each distinct k-1 prefix and suffix, create a vertex number
    */
    char buff[k+3]; // +1 for \n, +1 for \0 terminator, +1 for \n in input
    while (fgets(buff, k+2, stdin) != NULL) {
            //erase \n
        buff[k] = 0; 

        char *str1 = (char *)malloc(sizeof(char)*(k));
        char *str2 = (char *)malloc(sizeof(char)*(k));
        if (!str1 || !str2) {
            fprintf(stderr,"Out of memory for strings\n");
            return NULL;
        }
        strcpy(str1, buff+1);
        Label second_v  = get_vertex_label(graph, str1);
        buff[k-1] = 0;
        strcpy(str2, buff);
        Label first_v = get_vertex_label(graph, str2);

        insert_edge(graph, first_v, second_v);
    }

    return graph;
}
    
/*
** Read input, call build graph, find start and end vertices, find Euler tour, print
*/
int 
main(int argc, char *argv[]) {
    if (argc != 1) {
        usage(argv[0]);
        return(EXIT_FAILURE);
    }

    htable = inithashtable();

    Graph *graph = read_input();
    if (!graph)
        return(EXIT_FAILURE);
#ifdef DEBUG
    dumpHashTable(htable);
    print_graph(graph);
#endif

    Label start = find_start(graph);
    Label end   = find_end(graph);
    insert_edge(graph, end, start);
#ifdef DEBUG
    print_graph(graph);
#endif

    LabelList path = find_euler_path(graph, start);

    print_path(graph, path);
    
    return EXIT_SUCCESS;
}
